from django.shortcuts import render,redirect
from app.models import *
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View
import requests
import xmltodict
import json
from django.core.serializers import serialize
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.views import APIView
from PIL import Image,ImageDraw  # ImageDraw 绘画库   Image 图片库
from PIL import ImageFont  # 字体库
import random,io  # random 随机库     io 文件流
import requests
from redis import Redis
# 导入上传文件夹配置
from  day01.settings import UPLOAD_ROOT
import os


redis = Redis("localhost",6379)


# 导入加密库
import hashlib

# 加密方法
def make_password(mypass):
    # md5算法
    mypass = hashlib.md5()
    # 对字符串进行编译(加盐操作)
    mypass.update('123'.encode(encoding='utf-8'))
    # 返回密文
    return mypass.hexdigest()

# 注册接口
class Register(APIView):
    def get(self,request):
        # 接收参数
        username = request.GET.get('username','未收到用户')
        password = request.GET.get('password','未收到密码')

        # 获取随机验证码
        code = request.GET.get('code','未收到验证码')
        # code =

        # 获取redis中的验证码
        mycode = redis.get('code')
        mycode = mycode.decode('utf-8')
        print('--------------------------')
        print(mycode)

        if code != mycode:
            res = {}
            res['code'] = 405
            res['message'] = '验证码输入错误'
            return Response(res)

        # 排重操作
        user = User.objects.filter(username=username).first()
        if user:
            res = {}
            res['code'] = 405
            res['message'] = '用户已经存在'
            return Response(res)

        # 进行入库逻辑 加密
        user = User(username=username,password=make_password(password),type=0)
        user.save()

        # 返回结果
        res = {}
        res['code'] = 200
        res['message'] = '注册成功'
        return Response(res)


# 登录接口
class Login(APIView):
    def post(self,request):
        # 接收参数
        username = request.POST.get('username', '未收到用户')
        password = request.POST.get('password', '未收到密码')

        # 查询数据
        user = User.objects.filter(username=username,password=make_password(password)).first()

        if user:
            res = {}
            res['id'] = user.id
            res['code'] = 200
            res['message'] = '登录成功'
            res['username'] = user.username
            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '您的用户名或密码错误'
            return Response(res)

# 定义验证码类
class MyCode(View):
    # 定义随机颜色方法
    def get_random_color(self):
        R = random.randrange(255)  # randrange 取值范围
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)

    # 定义随机验证码
    def get(self, request):
        # 定义画布大小 宽，高
        img_size = (120,50)
        # 定义图像 颜色种类,画布，背景颜色
        image = Image.new("RGB", img_size,'white')
        # 定义画笔对象 图片对象,颜色类型
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机字符组成
        source = '0123456789asdfghjkl'
        # 定义好容器，用来接收随机字符串
        code_str = ''
        # 定义四个字符
        for i in range(4):
            # 获取随机颜色 字体颜色
            text_color = self.get_random_color()
            # 获取随机字符串
            tmp_num = random.randrange(len(source))
            # 获取字符集
            random_str = source[tmp_num]
            # 将随机生成的字符串添加到定义好的容器中
            code_str += random_str
            # 将文字输入绘图
            draw.text((10+30*i,20),random_str,text_color)
        # 建立io文件流
        buf = io.BytesIO()
        # 将图片保存到内存中
        image.save(buf,'png')
        # 将验证码存储到redis中
        redis.set('code',code_str)
        # 将验证码存储到session中
        # request.session['code'] = code_str
        # print(request.session['code'])
        # 返回文件流图像 第二个参数声明头部信息
        return HttpResponse(buf.getvalue(),'image/png')


# 定义新浪微博回调方法
def weibo_back(request):
    # 获取新浪微博回调的code
    code = request.GET.get('code')
    # 微博认证机制
    access_token_url = "https://api.weibo.com/oauth2/access_token"
    #发起http请求
    re_dict = requests.post(
        access_token_url,
        data={
            # app_id 应用id
            "client_id":"2624779353",
            # app_secret 秘钥
            "client_secret":"29b065cf03dd29ddcebe7f8fc02a4a47",
            # 授权类型 code
            "grant_type":"authorization_code",
            # code 参数
            "code":code,
            # 回调网址
            "redirect_uri":"http://127.0.0.1:8000/weibo"
        }
    )
    # 打印数据
    re_dict = re_dict.text
    # 强转数据类型
    re_dict = eval(re_dict)
    print(re_dict)
    # 判断是否用新浪微博账号登录'
    user = User.objects.filter(username=str(re_dict['uid'])).first()
    sina_id = ''
    user_id = ''
    if user:
        # 代表曾经登录并且生成过账号
        sina_id = user.username,
        user_id = user.id
    else:
        # 自动创建账号
        user = User(username=str(re_dict['uid']),password=make_password(''),type=0)
        # 保存
        user.save()
        sina_id = str(re_dict['uid'])
        # 查询数据库id
        user = User.objects.filter(username=str(re_dict['uid'])).first()
        user_id = user.id
    # 进行跳转
    return redirect('http://localhost:8080?sina_id='+sina_id+"&uid="+str(user_id))


# 定义文件上传类
class UploadFile(View):
    def post(self,request):
        img = request.FILES.get('file')
        # 建立文件流
        f = open(os.path.join(UPLOAD_ROOT,'',img.name),'wb')
        # 写文件 遍历文件流
        for chunk in img.chunks():
            f.write(chunk)
        f.close()

        # 返回结果
        return HttpResponse(json.dumps({'filename':img.name}),content_type='application/json')

# 序列化
class UserSer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

class CategorySer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class CourseSer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = '__all__'


# 定义课程分类接口
class CategoryList(APIView):
    def get(self,request):
        cates = Category.objects.all()
        # 注instance 用于接收序列化的对象,many表示是queryset对象
        cates_ser = CategorySer(instance=cates,many=True)
        return Response(cates_ser.data)

# 课程入库
class AddCourse(APIView):
    def get(self,request):
        # 接收参数
        title = request.GET.get('title','')
        desc = request.GET.get('desc','')
        category = request.GET.get('category','')
        img = request.GET.get('img','')
        uid = request.GET.get('uid','')
        price = request.GET.get('price','')
        # 查询分类
        cate = Category.objects.filter(name=category).first()
        # 排重操作
        course = Course.objects.filter(title=title).first()
        if course:
            res = {}
            res['code'] = 405
            res['message'] = '课程已经存在'
            return Response(res)

        # 进行入库逻辑
        course = Course(title=title,desc=desc,img=img,uid=int(uid),price=int(price),cid=int(cate.id))
        course.save()

        # 返回结果
        res = {}
        res['code'] = 200
        res['message'] = '添加课程成功'
        return Response(res)


# 课程列表
class CourseList(APIView):
    def get(self,request):
        # 当前页
        page = request.GET.get("page",1)
        # 每页条数
        size = request.GET.get("size",1)
        # 开始位置
        data_start = (int(page)-1)*int(size)
        # 结束位置
        data_end = int(page) * int(size)

        # 获取课程列表
        clist = Course.objects.all()[data_start:data_end]
        # 获取总条数
        count = Course.objects.count()

        # 序列化
        clist_ser = CourseSer(clist,many=True)
        # 返回容器
        res = {}
        res['total'] = count
        res['data'] = clist_ser.data
        # 返回结果
        return Response(res)

# 单独课程接口
class SingleCourse(APIView):
    def get(self,request):
        #获取参数
        id = request.GET.get('id')
        # 获取单课程
        course = Course.objects.filter(id=int(id)).first()
        # 序列化
        course_ser = CourseSer(course)
        # 返回结果
        return Response(course_ser.data)

# 单独用户接口
class SingleUser(APIView):
    def get(self, request):
        # 获取参数
        id = request.GET.get('id')
        print(id,'---------------')
        # 获取一个用户
        user = User.objects.filter(id=id).first()
        # 序列化
        user_ser = UserSer(user)
        # 返回结果
        return Response(user_ser.data)
























# class UserSer(serializers.ModelSerializer):
#     class Meta:
#         model = User
#         fields = '__all__'

client_appid = 'wxfc9dd85023bb8840'
Mch_id = '1555664621'
Mch_key = 'Jiyun123456Jiyun123456Jiyun12345'


def myindex(request):
    return HttpResponse('这里是首页')


def myback(request):
    return HttpResponse('这里是回调网址')


def get_nonce_str():
    import uuid
    return str(uuid.uuid4()).replace('-', '')


def getWxPayOrdrID():
    import datetime

    date = datetime.datetime.now()
    # 根据当前系统时间来生成商品订单号。时间精确到微秒
    payOrdrID = date.strftime("%Y%m%d%H%M%S%f")

    return payOrdrID


# 生成签名的函数
def paysign(appid, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee):
    ret = {
        "appid": appid,
        "body": body,
        "mch_id": mch_id,
        "nonce_str": nonce_str,
        "notify_url": notify_url,
        "openid": openid,
        "out_trade_no": out_trade_no,
        "spbill_create_ip": spbill_create_ip,
        "total_fee": total_fee,
        "trade_type": 'JSAPI'
    }

    # 处理函数，对参数按照key=value的格式，并按照参数名ASCII字典序排序
    stringA = '&'.join(["{0}={1}".format(k, ret.get(k)) for k in sorted(ret)])
    stringSignTemp = '{0}&key={1}'.format(stringA, Mch_key)
    sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
    return sign.upper()


def generate_sign(param):
    '''生成签名'''
    stringA = ''
    ks = sorted(param.keys())
    print(param)
    # 参数排序
    for k in ks:
        stringA += (k + '=' + param[k] + '&')
    # 拼接商户KEY
    stringSignTemp = stringA + "key=" + Mch_key
    # md5加密,也可以用其他方式
    hash_md5 = hashlib.md5(stringSignTemp.encode('utf8'))
    sign = hash_md5.hexdigest().upper()
    return sign


# 获取全部参数信息，封装成xml,传递过来的openid和客户端ip，和价格需要我们自己获取传递进来
def get_bodyData(openid, client_ip, price):
    body = 'Mytest'  # 商品描述
    notify_url = 'http://localhost:8000/back'  # 填写支付成功的回调地址，微信确认支付成功会访问这个接口
    nonce_str = get_nonce_str()  # 随机字符串
    out_trade_no = getWxPayOrdrID()  # 商户订单号
    total_fee = str(price)  # 订单价格，单位是 分

    # 获取签名
    sign = paysign(client_appid, body, Mch_id, nonce_str, notify_url, openid, out_trade_no, client_ip, total_fee)

    bodyData = '<xml>'
    bodyData += '<appid>' + client_appid + '</appid>'  # 小程序ID
    bodyData += '<body>' + body + '</body>'  # 商品描述
    bodyData += '<mch_id>' + Mch_id + '</mch_id>'  # 商户号
    bodyData += '<nonce_str>' + nonce_str + '</nonce_str>'  # 随机字符串
    bodyData += '<notify_url>' + notify_url + '</notify_url>'  # 支付成功的回调地址
    bodyData += '<openid>' + openid + '</openid>'  # 用户标识
    bodyData += '<out_trade_no>' + out_trade_no + '</out_trade_no>'  # 商户订单号
    bodyData += '<spbill_create_ip>' + client_ip + '</spbill_create_ip>'  # 客户端终端IP
    bodyData += '<total_fee>' + total_fee + '</total_fee>'  # 总金额 单位为分
    bodyData += '<trade_type>JSAPI</trade_type>'  # 交易类型 小程序取值如下：JSAPI

    bodyData += '<sign>' + sign + '</sign>'
    bodyData += '</xml>'

    return bodyData


# 统一下单支付接口
def payOrder(request):
    import time
    # 获取价格 单位是分
    price = int(request.GET.get("price", 1))

    # 获取客户端ip
    client_ip, port = request.get_host().split(":")

    # 获取小程序openid
    # openid='of2Fa5C2BNn77OOh1hfydxK4pVJc'
    openid = request.GET.get("openid")

    # 请求微信的url
    url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'

    # 拿到封装好的xml数据
    body_data = get_bodyData(openid, client_ip, price)

    # 获取时间戳
    timeStamp = str(int(time.time()))

    # 请求微信接口下单
    respone = requests.post(url, body_data.encode("utf-8"), headers={'Content-Type': 'application/xml'})
    print(respone.content)
    # 回复数据为xml,将其转为字典
    content = xmltodict.parse(respone.content)
    print(content)

    return_code = content['xml']['return_code']

    if return_code == 'SUCCESS':
        prepay_id = content['xml']['prepay_id']
        # 时间戳
        timeStamp = str(int(time.time()))
        # 5. 五个参数
        data = {
            "appId": client_appid,
            "nonceStr": get_nonce_str(),
            "package": "prepay_id=" + prepay_id,
            "signType": 'MD5',
            "timeStamp": timeStamp,
        }
        # 6. paySign签名
        paySign = generate_sign(data)
        data["paySign"] = paySign  # 加入签名
        print(data)
        # 7. 传给前端的签名后的参数
        return JsonResponse(data, safe=False, json_dumps_params={'ensure_ascii': False})
    else:
        return HttpResponse("请求支付失败")


def product_all(request):
    res = User.objects.all()
    mylist = json.loads(serialize('json', res, ensure_ascii=False))
    return JsonResponse(mylist, safe=False, json_dumps_params={'ensure_ascii': False})


class MyUser(APIView):
    def get(self, request):
        users = User.objects.all()
        # 注instance用于接受序列化的对象，many表示是queryset对象
        books_ser = UserSer(users, many=True)
        return Response(books_ser.data)



# 方法视图
def index(request):
    # 读库
    res = User.objects.all()
    #手动序列化
    mylist = json.loads(serialize('json',res,ensure_ascii=False))
    # 返回json
    return JsonResponse(mylist,sofe=False,json_dumps_params={'ensure_ascii':False})

def myuser(request):
    user = User.objects.all()
    return render(request,'myuser.html',locals())

# 模板练习
def mytem(request):
    title = 'Hello'
    num = 100
    li = [1,2,3,4,5,6]
    dic= {'name':'小明','age':12}

    #读库
    res = User.objects.all()


    return render(request,'index.html',locals())



